#include "pila.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/* ******************************************************************
 *                        PRUEBAS UNITARIAS							*
 * *****************************************************************/

/* Función auxiliar para imprimir si estuvo OK o no. */
void print_test(char* name, bool result) {
    printf("%s: %s\n", name, result? "OK" : "ERROR");
}

void prueba_pila () {
	 /* Declaro las variables a utilizar */
	pila_t* p1;
	int *a = malloc (sizeof(int));
	int *b = malloc (sizeof(int));
	int *c = malloc (sizeof(int));
	if ((!a) || (!b) || (!c)) return;
	*a = 20;
	*b = 35;
	*c = 12;
    void* valor1 = &a;
    void* valor2 = &b;
    void* valor3 = &c;
    
    /* Pruebo la creación de una pila vacía */
    p1 = pila_crear();
    print_test("Prueba pila crear p1", p1 != NULL);
    print_test("Prueba pila_esta_vacia p1 es true", pila_esta_vacia(p1) == true);

    /* Pruebo ver tope y desapilar de una pila vacía */
    print_test("Prueba ver tope p1 (vacia) es NULL", pila_ver_tope(p1) == NULL);
    print_test("Prueba pila desapilar p1 (vacia) es NULL", pila_desapilar(p1) == NULL);
    
    /* Pruebo apilar un elemento a una pila vacía */
    print_test("Prueba apilar p1 (vacía) es true", pila_apilar(p1,valor1) == true);
    print_test("Prueba ver tope p1 es 20", pila_ver_tope(p1) == valor1);
    print_test("Prueba ver tope p1 es 20 (para ver si solo lo ve)", pila_ver_tope(p1) == valor1);
    print_test("Prueba pila_esta_vacia p1 es false", pila_esta_vacia(p1) == false);
    
    /* Pruebo apilar a una pila con un elemento */

    print_test("Prueba apilar p1 (con un elemento) es true", pila_apilar(p1,valor2) == true);
    print_test("Prueba ver tope p1 es 35", pila_ver_tope(p1) == valor2);
    print_test("Prueba ver tope p1 es 35 (para ver si solo lo ve)", pila_ver_tope(p1) == valor2);
    print_test("Prueba pila_esta_vacia p1 es false", pila_esta_vacia(p1) == false);
    
    /* Pruebo desapilar de una pila con dos elementos */
    print_test("Prueba pila desapilar p1 (con dos elementos) es 35", pila_desapilar(p1) == valor2);
    
    /* Pruebo desapilar de una pila con un elemento */
    print_test("Prueba pila desapilar p1 (con un elemento) es 20", pila_desapilar(p1) == valor1);
    print_test("Prueba pila_esta_vacia p1 es true", pila_esta_vacia(p1) == true);
    
    /* Pruebo apilar muchos elementos a una pila vacía */
    printf ("\nPRUEBAS DE VOLUMEN.\n\n");
    bool ok = true;
    for (int i=1; i<=10000000; i++) {
		ok = pila_apilar(p1,valor3);
		if (!ok) break;
    }
    print_test("Prueba apilar 10kk de elementos", ok);
    print_test("Prueba ver tope p1 es 12", pila_ver_tope(p1) == valor3);
    
    /* Pruebo desapilar muchos elementos de una pila */
	ok = true;
	for (int i=1; i<=5000000; i++) {
		ok = (pila_desapilar(p1) != NULL);
		if (!ok) break;
	}
    print_test("Prueba desapilar 5kk de elementos", ok);
    
    /* Pruebo apilar uno mas */
    print_test("Prueba apilar p1 un elem mas es true", pila_apilar(p1,valor3) == true);
    print_test("Prueba ver tope p1 es 12", pila_ver_tope(p1) == valor3);
    
    /* Pruebo desapilar mas elementos */
	ok = true;
	for (int i=1; i<=5000000; i++) {
		ok = (pila_desapilar(p1) != NULL);
		if (!ok) break;
	}
    print_test("Prueba desapilar 5kk de elementos", ok);;
    print_test("Prueba ver tope p1 es 12", pila_ver_tope(p1) == valor3);
    print_test("Prueba pila desapilar p1 un elem mas es 12", pila_desapilar(p1) == valor3);
    print_test("Prueba pila_esta_vacia p1 es true", pila_esta_vacia(p1) == true);
    
    free(a); free(b); free(c);
    /* Destruyo la pila para liberar la memoria pedida */
    pila_destruir (p1,NULL);
    
}

/* ******************************************************************
 *                        PROGRAMA PRINCIPAL						*
 * *****************************************************************/

int main () {
	
	printf ("\nCOMIENZO DE PRUEBAS PILA.\n\n");
	
	prueba_pila ();
	
	printf ("\nFIN DE PRUEBAS PILA.\n\n");
	return 0;
}
